From cfd9118e9c0de812d0673beabe225b8fd630e4b1 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 26 Apr 2005 09:31:16 +0000 Subject: [PATCH] bitkeeper revision 1.1385 (426e0a64bO3xeXCBe6s8h2DX9QnqbQ) Simple batched writable p.t. support for multi-processor guests. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 38 +++++++++++++++++++++++++++----------- xen/include/asm-x86/mm.h | 2 ++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index fdf2d8af71..ec6a2dd604 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2477,9 +2477,11 @@ void ptwr_flush(struct domain *d, const int which) int i; unsigned int modified = 0; - // not supported in combination with various shadow modes! - ASSERT( !shadow_mode_enabled(d) ); - + ASSERT(!shadow_mode_enabled(d)); + + if ( unlikely(d->arch.ptwr[which].ed != current) ) + write_ptbase(d->arch.ptwr[which].ed); + l1va = d->arch.ptwr[which].l1va; ptep = (unsigned long *)&linear_pg_table[l1_linear_offset(l1va)]; @@ -2513,7 +2515,7 @@ void ptwr_flush(struct domain *d, const int which) /* Ensure that there are no stale writable mappings in any TLB. */ /* NB. INVLPG is a serialising instruction: flushes pending updates. */ - local_flush_tlb_one(l1va); /* XXX Multi-CPU guests? */ + flush_tlb_one_mask(d->cpuset, l1va); PTWR_PRINTK("[%c] disconnected_l1va at %p now %lx\n", PTWR_PRINT_WHICH, ptep, pte); @@ -2579,6 +2581,9 @@ void ptwr_flush(struct domain *d, const int which) */ d->arch.ptwr[which].l1va = 0; + + if ( unlikely(d->arch.ptwr[which].ed != current) ) + write_ptbase(current); } static int ptwr_emulated_update( @@ -2741,7 +2746,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) page = &frame_table[pfn]; /* We are looking only for read-only mappings of p.t. pages. */ - if ( ((l1e_get_flags(pte) & (_PAGE_RW | _PAGE_PRESENT)) != _PAGE_PRESENT) || + if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) || ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) || (page_get_owner(page) != d) ) { @@ -2753,10 +2758,6 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) goto emulate; #endif - /* Writable pagetables are not yet SMP safe. Use emulator for now. */ - if ( d->exec_domain[0]->ed_next_list != NULL ) - goto emulate; - /* Get the L2 index at which this L1 p.t. is always mapped. */ l2_idx = page->u.inuse.type_info & PGT_va_mask; if ( unlikely(l2_idx >= PGT_va_unknown) ) @@ -2785,7 +2786,21 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) (l2_idx == d->arch.ptwr[PTWR_PT_ACTIVE].l2_idx)) ) which = PTWR_PT_ACTIVE; } - + + /* + * If this is a multi-processor guest then ensure that the page is hooked + * into at most one L2 table, which must be the one running on this VCPU. + */ + if ( (d->exec_domain[0]->ed_next_list != NULL) && + ((page->u.inuse.type_info & PGT_count_mask) != + (!!(page->u.inuse.type_info & PGT_pinned) + + (which == PTWR_PT_ACTIVE))) ) + { + /* Could be conflicting writable mappings from other VCPUs. */ + cleanup_writable_pagetable(d); + goto emulate; + } + PTWR_PRINTK("[%c] page_fault on l1 pt at va %lx, pt for %08x, " "pfn %lx\n", PTWR_PRINT_WHICH, addr, l2_idx << L2_PAGETABLE_SHIFT, pfn); @@ -2810,12 +2825,13 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) d->arch.ptwr[which].l1va = addr | 1; d->arch.ptwr[which].l2_idx = l2_idx; + d->arch.ptwr[which].ed = current; /* For safety, disconnect the L1 p.t. page from current space. */ if ( which == PTWR_PT_ACTIVE ) { l2e_remove_flags(pl2e, _PAGE_PRESENT); - local_flush_tlb(); /* XXX Multi-CPU guests? */ + flush_tlb_mask(d->cpuset); } /* Temporarily map the L1 page, and make a copy of it. */ diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 99e0208406..014fa7e45d 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -301,6 +301,8 @@ struct ptwr_info { unsigned int l2_idx; /* NB. Only used for PTWR_PT_ACTIVE. */ /* Info about last ptwr update batch. */ unsigned int prev_nr_updates; + /* Exec domain which created writable mapping. */ + struct exec_domain *ed; }; #define PTWR_PT_ACTIVE 0 -- 2.30.2